package org.dromara.common.websocket.handler

import io.github.oshai.kotlinlogging.KotlinLogging
import org.dromara.common.core.domain.model.LoginUser
import org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY
import org.dromara.common.websocket.dto.WebSocketMessageDto
import org.dromara.common.websocket.holder.WebSocketSessionHolder
import org.dromara.common.websocket.utils.WebSocketUtils.publishMessage
import org.dromara.common.websocket.utils.WebSocketUtils.sendPongMessage
import org.springframework.web.socket.*
import org.springframework.web.socket.handler.AbstractWebSocketHandler
import java.io.IOException

/**
 * WebSocketHandler 实现类
 *
 * @author LikeYouDo
 * @date 2025/09/22
 */
class PlusWebSocketHandler : AbstractWebSocketHandler() {
    companion object {
        private val log = KotlinLogging.logger { }
    }

    /**
     * 连接成功后
     */
    @Throws(IOException::class)
    override fun afterConnectionEstablished(session: WebSocketSession) {
        val loginUser = session.attributes[LOGIN_USER_KEY] as LoginUser?
        if (loginUser == null) {
            session.close(CloseStatus.BAD_DATA)
            log.info { "[connect] invalid token received. sessionId: ${session.id}" }
            return
        }
        loginUser.userId?.let { WebSocketSessionHolder.addSession(it, session) }
        log.info { "[connect] sessionId: ${session.id},userId:${loginUser.userId},userType:${loginUser.userType}" }
    }

    /**
     * 处理接收到的文本消息
     *
     * @param session WebSocket会话
     * @param message 接收到的文本消息
     * @throws Exception 处理消息过程中可能抛出的异常
     */
    @Throws(Exception::class)
    override fun handleTextMessage(session: WebSocketSession, message: TextMessage) {
        // 从WebSocket会话中获取登录用户信息
        val loginUser = session.attributes[LOGIN_USER_KEY] as LoginUser

        // 创建WebSocket消息DTO对象
        val webSocketMessageDto = WebSocketMessageDto()
        loginUser.userId?.let { webSocketMessageDto.sessionKeys = mutableListOf(it) }
        webSocketMessageDto.message = message.payload
        publishMessage(webSocketMessageDto)
    }

    /**
     * 处理接收到的二进制消息
     *
     * @param session WebSocket会话
     * @param message 接收到的二进制消息
     * @throws Exception 处理消息过程中可能抛出的异常
     */
    @Throws(Exception::class)
    override fun handleBinaryMessage(session: WebSocketSession, message: BinaryMessage) {
        super.handleBinaryMessage(session, message)
    }

    /**
     * 处理接收到的Pong消息（心跳监测）
     *
     * @param session WebSocket会话
     * @param message 接收到的Pong消息
     * @throws Exception 处理消息过程中可能抛出的异常
     */
    @Throws(Exception::class)
    override fun handlePongMessage(session: WebSocketSession, message: PongMessage) {
        sendPongMessage(session)
    }

    /**
     * 处理WebSocket传输错误
     *
     * @param session   WebSocket会话
     * @param exception 发生的异常
     * @throws Exception 处理过程中可能抛出的异常
     */
    @Throws(Exception::class)
    override fun handleTransportError(session: WebSocketSession, exception: Throwable) {
        log.error { "[transport error] sessionId: ${session.id} , exception:${exception.message}" }
    }

    /**
     * 在WebSocket连接关闭后执行清理操作
     *
     * @param session WebSocket会话
     * @param status  关闭状态信息
     */
    override fun afterConnectionClosed(session: WebSocketSession, status: CloseStatus) {
        val loginUser = session.attributes[LOGIN_USER_KEY] as LoginUser?
        if (loginUser == null) {
            log.info { "[disconnect] invalid token received. sessionId: ${session.id}" }
            return
        }
        loginUser.userId?.let { WebSocketSessionHolder.removeSession(it) }
        log.info { "[disconnect] sessionId: ${session.id},userId:${loginUser.userId},userType:${loginUser.userType}" }
    }

    /**
     * 指示处理程序是否支持接收部分消息
     *
     * @return 如果支持接收部分消息，则返回true；否则返回false
     */
    override fun supportsPartialMessages(): Boolean {
        return false
    }

}
